<?php

declare(strict_types=1);

namespace App\Model\Service;

use App\Helpers\ConfigUtil;
use App\Helpers\Helper;
use App\Model\CoinLog;
use App\Model\Gift;
use App\Model\GiftBatchLog;
use App\Model\GiftLog;
use App\Model\Message;
use App\Model\Setting\SettingAllocate;
use App\Model\UserBlacklist;
use App\Model\UserCoin;
use App\Model\UserProfile;
use Exception;
use Hyperf\DbConnection\Db;

class GiftService
{
    //是否需要领取
    public $giftNeedFetch = true;
    //系统礼物
    public $giftInfo = [];
    public $userId = 0;
    //今天赠送记录
    public $sendLogs = [];
    //分配的主播ID
    public $hostIds = [];

    /**
     * 领取所有未领取的礼物
     */
    static function fetchAll($senderId = 0, $receiverId = 0)
    {
        if (!$senderId || !$receiverId) return false;
        //获取所有未领取, 且有效的礼物
        $giftLogs = GiftLog::checkUnFetched($senderId, $receiverId);
        //赠送记录不匹配
        if (empty($giftLogs)) {
            log_user_result($receiverId, "Sender:{$senderId}==没有记录");
            return false;
        }

        //获取所有有效礼物记录
        $logIds = array_column($giftLogs, 'id');
        $giftCoin = array_sum(array_map(function ($val) {
            return $val['gift_coin'];
        }, $giftLogs));

        //领取
        self::doFetch($receiverId, $logIds, $giftCoin, $senderId);
        log_user_result($receiverId, "GiftCoin:{$giftCoin}==GiftLogIds:" . json_encode($logIds));
        return ['gift_num' => count($logIds), 'gift_id' => $giftLogs[count($giftLogs) - 1]['gift_id']];
    }

    static function fetchAllPushGift($senderId = 0, $receiverId = 0)
    {
        if (!$senderId || !$receiverId) return false;
        //获取所有未领取, 且有效的礼物
        $giftLogs = GiftLog::checkUnFetchedPushGift($senderId, $receiverId);
        //赠送记录不匹配
        if (empty($giftLogs)) {
            log_user_result($receiverId, "Sender:{$senderId}==没有记录");
            return false;
        }

        //获取所有有效礼物记录
        $logIds = array_column($giftLogs, 'id');
        $giftCoin = array_sum(array_map(function ($val) {
            return $val['gift_coin'];
        }, $giftLogs));
        //领取
        self::doFetchPushGift($receiverId, $logIds, $giftCoin, $senderId);
        log_user_result($receiverId, "GiftCoin:{$giftCoin}==GiftLogIds:" . json_encode($logIds));
        return ['gift_num' => count($logIds), 'gift_id' => $giftLogs[count($giftLogs) - 1]['gift_id']];
    }

    /**
     * @param $receiverId
     * @param $logIds
     * @param $giftCoin
     * @param $senderId
     * @return false|void
     */
    static function doFetchPushGift($receiverId,$logIds,$giftCoin,$senderId)
    {
        if (!$receiverId || empty($logIds) || !$giftCoin) return false;
        //生成订单号
        $orderId = ConsumeService::genOrderId($logIds[0], 'gift');

        //开启事务处理
        Db::beginTransaction();
        try {
            //修改状态
            GiftLog::whereIn('id', $logIds)->update([
                'flag' => GiftLog::STATUS_OK,
                'order_id' => $orderId
            ]);
            //平台抽成服务费记录
//            $serviceFee = ConsumeService::proccessServiceFee($giftCoin, $orderId, $receiverId);
            $serviceFee = 0;

            //主播实际收入
            $realInCome = $giftCoin - $serviceFee;
            //更新对方账户
            $remainCoin = UserCoin::gainIncome($receiverId, $realInCome);
            //添加流水记录
            CoinLog::addIncome(
                $receiverId,
                $realInCome,
                CoinLog::FROM_FEMALE_PUSH_GIFT,
                $remainCoin,
                $orderId,
                $senderId
            );
            //提交事务
            Db::commit();
        } catch (Exception $e) {
            log_error(__CLASS__ . "==doFetch_Exception:" . $e->getMessage());
            Db::rollback();
        }

        //魅力值，豪气值变更事件
        // make(EventDispatcherInterface::class)->dispatch(new ConsumeEvent($senderId, $receiverId, $giftCoin, $realInCome, false));
        return;
    }

    /**
     * 领取礼物
     */
    static function doFetch($receiverId = 0, $logIds = [], $giftCoin = 0, $senderId = 0)
    {
        if (!$receiverId || empty($logIds) || !$giftCoin) return false;
        //生成订单号
        $orderId = ConsumeService::genOrderId($logIds[0], 'gift');

        //开启事务处理
        Db::beginTransaction();
        try {
            //修改状态
            GiftLog::whereIn('id', $logIds)->update([
                'flag' => GiftLog::STATUS_OK,
                'order_id' => $orderId
            ]);
            //平台抽成服务费记录
            $serviceFee = ConsumeService::proccessServiceFee($giftCoin, $orderId, $receiverId);

            //主播实际收入
            $realInCome = $giftCoin - $serviceFee;
            //更新对方账户
            $remainCoin = UserCoin::gainIncome($receiverId, $realInCome);
            //添加流水记录
            CoinLog::addIncome(
                $receiverId,
                $realInCome,
                CoinLog::FROM_GET_SYSGIFT,
                $remainCoin,
                $orderId,
                $senderId
            );
            //提交事务
            Db::commit();
        } catch (Exception $e) {
            log_error(__CLASS__ . "==doFetch_Exception:" . $e->getMessage());
            Db::rollback();
        }

        //魅力值，豪气值变更事件
        // make(EventDispatcherInterface::class)->dispatch(new ConsumeEvent($senderId, $receiverId, $giftCoin, $realInCome, false));
        return;
    }

    /**
     * 分发名义私信礼物
     */
    function proccessSysGift($userId = 0, $groupItem = [])
    {
        $this->userId = $userId;
        $ret = ['result' => 0, 'push_uids' => []];
        if (!$this->checkLmt($userId)) return $ret;

        //分配的礼物信息
        $this->giftInfo = Gift::getInfo($groupItem['gift_id']);
        //赠送总数
        if (GiftLog::getAllCount('today', $this->giftInfo['id']) >= $groupItem['gift_num']) {
            return $ret;
        }

        //分配的主播
        $hostIds = UserProfile::getOnlineUsers(UserProfile::ROLE_HOST, 300);
        // shuffle($hostIds);
        //SettingAllocate::getAllocateHosts($groupItem['host_cate']);

        //获取有效推送主播
        $hostIds = $this->getValidHosts($hostIds);

        //赠送
        $ret['push_uids'] = $this->doSend(
            $hostIds,
            GiftLog::FROM_SYS_ONLINE,
            $groupItem['single_gift_num'],
            $groupItem['host_cate'],
            $groupItem['gift_expire_time']
        );
        return $ret;
    }

    /**
     * 限制
     */
    private function checkLmt($userId = 0)
    {
        //是否在限制用户中
        if (Helper::checkTempExcluded($userId)) {
            log_user_result($userId, "Excluded");
            return false;
        }

        //当天已经赠送的主播
        $this->sendLogs = GiftBatchLog::sendSysGiftLogs($userId, 'today');
        $count = count($this->sendLogs);
        log_user_result($userId, "SendSysGiftTimes:{$count}");
        //单个男用户赠送数量超限制
        if ($count >= ConfigUtil::getSysGiftLmt()) {
            return false;
        }

        //上次赠送的时间
        // $offtimeLmt = check_dev_env() ? 30 : 1200;
        // if ($count > 0 && $log = $this->sendLogs[$count - 1]) {
        //     if (strtotime($log['created_at']) > (time() - $offtimeLmt)) {
        //         log_user_result($userId, "LastSendLmt:{$log['created_at']}");
        //         return false;
        //     }
        // }
        return true;
    }

    /**
     * 获取有效的送礼声优ID
     */
    private function getValidHosts($hostIds = [])
    {
        //该用户拉黑的主播
        $blockUserIds = UserBlacklist::getList($this->userId, 'uid');

        //特定渠道的
        $excludeChannelHostIds = []; //config('busi.online_tip_enable') ? [] : CacheService::channelHosts(config('busi.exclude_channel'));

        //黑名单的主播
        $blackHosts = CacheService::blackHosts();

        //去除上述
        $onlineHostds = array_diff($hostIds, $blockUserIds, $excludeChannelHostIds, $blackHosts);

        //已经赠送的（当天）
        if (!$this->sendLogs) {
            log_user_result($this->userId, "OnlineHostIds:" . count($onlineHostds) . "==Block:" . count($blockUserIds) . "==ExlChannel:" . count($excludeChannelHostIds) . "==Black:" . count($blackHosts) . "==Origin:" . count($hostIds));
            return $onlineHostds;
        }

        $receiverUserIds = [];
        foreach ($this->sendLogs as $log) {
            $log['receive_user_id'] && $receiverUserIds = array_merge($receiverUserIds, json_decode($log['receive_user_id'], true));
        }

        //筛选当天赠送礼物大于N次(单个限制礼物数)的
        $countInfo = array_count_values($receiverUserIds);
        $countInfo = array_filter($countInfo, function ($v) {
            return $v >= ConfigUtil::sysGiftNumMaxToOne();
        });
        if (!$countInfo) {
            log_user_result($this->userId, "No_countInfo");
            return $onlineHostds;
        }

        //有效的在线声优(排除当天已经赠送N次以上的)
        $inValidHosts = array_keys($countInfo);
        $onlineHostds = array_diff($onlineHostds, $inValidHosts);

        log_user_result($this->userId, "Block:" . count($blockUserIds) . "==Black:" . count($blackHosts) . "==Valid:" . count($onlineHostds));
        return $onlineHostds;
    }

    /**
     * 赠送逻辑
     */
    private function doSend(
        $hosts = [],
        $from = GiftLog::FROM_SYS_ONLINE,
        $singleGiftNumLmt = 3,
        $hostCate = 1,
        $giftExpTime = 180
    ) {
        if (empty($hosts)) return [];
        // $maxCount = ConfigUtil::sysGiftHostMax();
        $allHostCount = count($hosts);
        $pickCount = $singleGiftNumLmt > $allHostCount ? $allHostCount : $singleGiftNumLmt;
        // $hostIds = array_slice($hosts, 0, $pickCount);
        $hostIds = array_rand(array_flip($hosts), (int)$pickCount);
        $pushUids = [];
        if (!is_array($hostIds)) $hostIds = [$hostIds];
        foreach ($hostIds as $hostId) {
            //添加送礼记录
            $record = GiftLog::addSysGiftRecord(
                $this->userId,
                $hostId,
                $from,
                $this->giftNeedFetch,
                $this->giftInfo,
                $giftExpTime
            );
            $record && array_push($pushUids, $hostId);
        }
        if (!$pushUids) return [];
        //批量记录
        $ret = GiftBatchLog::addRecord($this->userId, $pushUids, $this->giftInfo['id'], Gift::TYPE_SYS);
        log_user_result($this->userId, "GiftBatchUids({$hostCate}):" . json_encode($pushUids));
        //发送消息
        Message::sendGift($pushUids, $this->userId, $this->giftInfo, $this->giftNeedFetch);
        return $hostIds;
    }

    /**
     * 主播给男用户发名义礼物
     */
    function hostSendToMale($userId = 0, $hostIds = [])
    {
        if (empty($hostIds)) return;
        log_user_result($userId, $hostIds);
        $giftId = check_dev_env() ? 22 : 33;
        $giftInfo = Gift::getInfo($giftId);
        $giftExpTime = ConfigUtil::sysGiftExpireTime(true);
        foreach ($hostIds as $hostId) {
            //添加送礼记录
            $record = GiftLog::addSysGiftRecord(
                $hostId,
                $userId,
                GiftLog::FROM_HOST_TO_USER,
                true,
                $giftInfo,
                $giftExpTime
            );
            //发送消息
            $record && Message::sendGift($userId, $hostId, $giftInfo, true);
        }
        // if (!$pushUids) return false;
        //批量记录
        $ret = GiftBatchLog::addRecord($userId, [], $giftId, Gift::TYPE_SYS, $hostIds);
        return;
    }
}
